package com.qf.consumer.simple;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class ConsumerMain_manual {

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("cdm");

        Connection conn = factory.newConnection();
        Channel channel = conn.createChannel();

        channel.basicConsume("simple.que",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                try {
                    int i = 1 / 0;

                    System.out.println("consumerTag:" + consumerTag);
                    System.out.println("deliveryTag:" + envelope.getDeliveryTag());
                    System.out.println("body:" + new String(body, "utf-8"));

                    System.out.println("--------------------------------");
                    //确认消费(第二个参数表示是否将这个生产端之前未被确认的消息，一并确认。true-确认，false-不确认之前的，只确认当前这一条)
                    channel.basicAck(envelope.getDeliveryTag(),true);
                }catch (Exception e) {
                    /**
                     *  在重新消费时，一定要计数的。比如重新消费了3次或者5次，依然还是不成功，不能在重新消费了 -- 否则服务器的cpu压力剧增
                     *      计数时，采用redis的incr方法，基于消息的id作为key，进行计数的累增
                     *
                     *  当达到次数依然消费失败，我们需要经这条消息信息写入数据库的重试表中(交换机、路由键、消息、时间戳、重试次数)，记录到数据库重试表后，消费者将消息设置为不入队
                     *  我们会通过定时任务，扫描这张重试表，对未达到重试次数的消息进行重发。如果重试次数到一定程度依然是失败，说明业务代码有问题，要么就是消息中间件服务器有问题，此时人工介入。
                     */

                    //redis -- incr（key） -- key必须是动态，而且是和消息相关的，可以使用消息的id作为key的使用
//                    //将消息记录到数据库的重试表中
//                    channel.basicNack(envelope.getDeliveryTag(), true, false);
//                    return;


                    System.out.println("重新消费.....");
                    //不确认，重新入队--重新消费
                    //第三个参数表示是否重新入队，true-重新入队，重新消费。false-不入队，消息删除
                    channel.basicNack(envelope.getDeliveryTag(), true, true);

                }
            }
        });
    }
}
